<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  <script>
    /*
      class 类
      1. 类中定义的方法是不可枚举的，这和 es5 中不一致
      2. constructor() 方法是类的默认方法，通过 new 命令生成对象实例时，自动调用该方法
        2.1 如果 constructor() 方法没有显示定义，则会被默认添加一个空的 constructor()
        2.2 默认 constructor() 返回 this，也可以指定返回另外的一个对象
      3. 类必须用 new 来调用，而不能直接进行函数调用
      4. 类相当于实例的原型，所有在类中定义的方法，都会被实例继承。如果在一个方法前加上 static 关键字，就i表示该方法不会被实例继承，而是直接通过类来调用，这就是“静态方法”
        4.1 如果静态方法内部使用 this，则这个 this 指向的是类，而不是实例
        4.2 静态方法可以与非静态方法重名
        4.3 父类的静态方法可以被子类继承
      5. 静态属性：指的是 Class 本身的属性，即 Class.propName，而不是定义在实例对象 this 上的属性；
        5.1 在实例属性上加上 static 关键字来定义实例属性
      

      类也可以写成表达式的形式：const myClass = class Me {}


      继承：
      Class 可以使用 extends 关键字来实现继承，让子类继承父类的属性和方法
    */

    // 传统生成实例对象
    // function Point(x, y) {
    //   this.x = x;
    //   this.y = y;
    // }
    // Point.prototype.toString = function() {
    //   return `(${this.x}, ${this.y})`
    // }
    // const p = new Point(1, 2);


    // 用类来写
    class Point{
      constructor(x, y) {
        this.x = x;
        this.y = y;
      }

      toString() {
        return `(${this.x}, ${this.y})`
      }

      // 静态方法, 直接通过 类名.方法名 来调用
      static staticMethod() {
        // 内部的this指向了类
        console.log(this)
      }
    }
    console.log(typeof Point)
    console.log(Point === Point.prototype.constructor)

    // 1. 类中定义的方法是不可枚举的，这和 es5 中不一致
    // []
    console.log(Object.keys(Point.prototype))
    // ['constructor', 'toString']
    console.log(Object.getOwnPropertyNames(Point.prototype))


    // 静态方法可以继承父类的静态方法
    class Parent{
      static staticMethod() {
        console.log('parent staticMethod')
      }
    }
    class Child extends Parent{
    }
    console.dir(new Child())
  </script>

  <script>
    // 继承
    class Animal {
      constructor() {
        console.log('父类 constructor')
      }
    }
    class Duck extends Animal {
      constructor() {
        // 必须先调用 父类的构造函数
        super();
        console.log('子类 constructor')
      }
    }
    console.log(new Duck())
  </script>
</body>
</html>